<?php

use App\Http\Middleware\CheckToken;
use App\Http\Middleware\ForceCheckToken;
use App\Http\Resources\CommentRes;
use App\Http\Resources\EventRes;
use App\Models\Category;
use App\Models\Comment;
use App\Models\Event;
use App\Models\Invitation;
use App\Models\Tag;
use App\Models\User;
use App\Services\AuthService;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;

Route::post('login', function(Request $request, AuthService $authService){
    $user = $authService->login($request->all());
    if($user){
        $_token = Str::random(60);
        $token = Hash::make($_token);
        $token_uuid = Str::uuid()->toString();
        $token_created_at = now();
        if($user->update(compact('token', 'token_uuid', 'token_created_at'))){
            $token = $_token;
            $user = $user->only(['id', 'name', 'email','role']);
            return response()->json([
                "msg" => "Logged in successfully",
                "data"=>[
                    ...compact('token', 'token_uuid', 'token_created_at'),
                    "user"=> $user
                ]
            ],200);
        }
    }
    return response()->json([
        "msg" => "Login failed",
    ],401);
});
Route::post('register', function(Request $request, AuthService $authService){});

Route::middleware([ForceCheckToken::class])->group(function (){
    Route::get('/logout', function(Request $request){
        $user = $request->get("user");
        if($user){
            if($user->update([
                "token" => null,
                "token_uuid" => null,
                "token_created_at" => null,
            ])){
                return response()->json([
                    "msg" => "Logged out successfully",
                ]);
            }
        }
        return response()->json([
            "msg" => "Logged out failed",
        ]);
    });
    Route::post('/events',function (Request $request){});
    Route::post('/comments',function (Request $request){
        $v = \Illuminate\Support\Facades\Validator::make($request->all(),[
            "content"=>"required",
            "event_id"=>"required|exists:events,id",
            "user_id"=>"required|exists:users,id",
            "parent_id"=>"nullable|exists:comments,id",
        ]);
        if($v->fails()){
            return response()->json([
                "msg"=>"Validation failed",
                "errors"=>$v->errors()
            ],422);
        }
        $comment = Comment::create($request->except('user'));
        if($comment){
            return response()->json([
                "msg"=>"Comment created successfully",
                "data"=>[
                    "comment"=>[
                        "id"=>$comment->id,
                        "content"=>$comment->content,
                        "user"=>$comment->user->only(['id', 'name', 'email']),
                        "created_at"=>$comment->created_at->toDateTimeString(),
                        "replies"=>[]
                    ]
                ],

            ],201);
        }
        return response()->json([
            "msg"=>"Comment created failed"
        ],500);
    });
    Route::post('/events/invite',function (Request $request){
        $user = $request->get("user");
        if(!$user || $user->role!=="ADMIN"){
            return response()->json([
                "msg"=>"Permission denied",
            ],401);
        }
        $v = \Illuminate\Support\Facades\Validator::make($request->except('user'),[
            "event_id"=>"required|exists:events,id",
            "user_id"=>"required|exists:users,id",
        ]);
        if($v->fails()){
            return response()->json([
                "msg"=>"Validation failed",
                "errors"=>$v->errors()
            ],422);
        }
        $event = Event::find($request->get("event_id"));
        if($event->creator_id!=$user->id){
            return response()->json([
                "msg"=>"Permission denied",
            ],401);
        }
        $res = DB::table('invitations')->insert($request->except('user'));
        if($res){
            return response()->json([
                "msg"=>"Success",
            ],201);
        }
        return response()->json([
            "msg"=>"Something went wrong",
        ],500);
    });
    Route::post('/events/join',function (Request $request){
        $v = \Illuminate\Support\Facades\Validator::make($request->except('user'),[
            "event_id"=>"required|exists:events,id",
            "user_id"=>"required|exists:users,id",
        ]);
        if($v->fails()){
            return response()->json([
                "msg"=>"Validation failed",
                "errors"=>$v->errors()
            ],422);
        }
        $res = DB::table('event_attendee')->insert($request->except('user'));
        if($res){
            return response()->json([
                "msg"=>"Joined event successfully",
            ],201);
        }
        return response()->json([
            "msg"=>"Something went wrong",
        ],500);
    });
    Route::get('/users',function (Request $request){
        $user = $request->get("user");
        if($user->role!=="ADMIN"){
            return response()->json([
                "msg"=>"Not allowed",
            ],401);
        }
        $inviting_to = $request->get("inviting_to");
        $users = User::select(["id","name","email","role"]);
        if($inviting_to){
            $event = Event::find($inviting_to);
            if($event){
                $invited = $event->invitedUsers->pluck("id")->toArray();
                $users = $users->whereNotIn("id", $invited);
            }
        }
        $s = $request->get("s");
        $users = $users->whereAny(['name','email'], 'like', "%{$s}%")->get();
        return response()->json([
            "msg"=>"Success",
            "data"=> [
                "users"=>$users
        ]
        ],200);
    });
    Route::delete('/invitations', function (Request $request){
        $user = $request->get("user");
        $v = \Illuminate\Support\Facades\Validator::make($request->except('user'),[
            "event_id"=>"required|exists:events,id",
            "user_id"=>"required|exists:users,id",
        ]);
        if($v->fails()){
            return response()->json([
                "msg"=>"Validation failed",
                "errors"=>$v->errors()
            ],422);
        }
        $event = Event::find($request->get("event_id"));
        if($event->creator_id!=$user->id){
            return response()->json([
                "msg"=>"Permission denied",
            ],401);
        }
        try{
            DB::transaction(function () use ($event,$request){
                DB::table('event_attendee')->where([
                    ["event_id",'=',$request->get("event_id")],
                    ["user_id",'=',$request->get("user_id")],
                ])->delete();
                DB::table('invitations')->where([
                    ["event_id",'=',$request->get("event_id")],
                    ["user_id",'=',$request->get("user_id")],
                ])->delete();
            });
        }
        catch(\Exception $e){
            return response()->json([
                "msg"=>"Something went wrong",
                "errors"=>$e->getMessage()
            ],500);
        }
        return response()->json([
            "msg"=>"Success",
        ],200);
    });
});


Route::middleware([CheckToken::class])->group(function (){
    Route::get('/events',function (Request $request) {
        $title = $request->input('title');
        $category = $request->input('category');
        $start_at = $request->input('start_at');
        $end_at = $request->input('end_at');
        $tags = $request->input('tags');
        $tag_rel = $request->input('tag_rel','Or');
        $events = Event::select(['id','title','start_at','end_at','location','type','capacity','category_id','creator_id'])
            //->with(['category:id,name',"creator"])
        ->when($title,function($q,$title){
            $q->where("title", "like", "%$title%");
        })->when($category,function($q,$category){
            $q->where("category_id", $category);
        })->when($start_at,function($q,$start_at){
            $q->where("start_at", ">=", Carbon::createFromTimeString($start_at)->format("Y-m-d H:i:s"));
        })->when($end_at,function($q,$end_at){
            $q->where("end_at", "<=", Carbon::createFromTimeString($end_at)->format("Y-m-d H:i:s"));
        })->when($tags,function($q,$tags) use ($tag_rel){
            $q->whereHas('tags',function($q) use ($tags, $tag_rel){
                if($tag_rel=='Or'){
                    $q->whereIn("tags.id", $tags);
                }
                else {
                    $q->select('event_tag.event_id')
                        ->whereIn("tags.id", $tags)
                        ->groupBy("event_tag.event_id")
                        ->havingRaw("count(distinct tags.id) = ?",[count($tags)]);
                    // SELECT COUNT(*) AS aggregate
                    // FROM `events`
                    // WHERE EXISTS (
                    //    SELECT `event_tag`.`event_id`
                    //    FROM `tags`
                    //    INNER JOIN `event_tag` ON `tags`.`id` = `event_tag`.`tag_id`
                    //    WHERE `events`.`id` = `event_tag`.`event_id`
                    //                AND `tags`.`id` IN (1, 3)
                    //    GROUP BY `event_tag`.`event_id`
                    //    HAVING COUNT(DISTINCT tags.id) = 2
                    // )
                }

            });
        })
            ->orderBy("id", "desc")->paginate($request->input('per_page',10));
//        $events->transform(function($event){
//            unset($event->description);
//            return $event;
//        });
        return response()->json([
            "title"=>$title,
            "msg" => "Success",
            "data"=> new \App\Http\Resources\EventCollection($events)
        ],200);
    });
    Route::get('/categories',function (Request $request) {
        return response()->json([
            "msg" => "Success",
            "data" => ["categories"=>Category::select("id","name")->orderBy("name")->get()]
        ]);
    });
    Route::get('/tags',function (Request $request) {
        return response()->json([
            "msg" => "Success",
            "data" => ["tags"=>Tag::select("id","name")->orderBy("name")->get()]
        ]);
    });
    Route::get('/events/{event_id}',function (Request $request, $event_id ){
        $event = Event::with(['participants','comments','invitedUsers'])->where("id",$event_id)->first();
        if($event){
            return response()->json([
                "msg" => "Success",
                "data"=>[
                    "event"=>EventRes::make($event)
                ]
            ],200);
        }
        return response()->json([
            "msg" => "Not found",
        ],404);
    });
    Route::get('/events/{event_id}/comments',function (Request $request, $event_id){
        $event = Event::with(['comments' => function ($query) {
            $query->whereNull('parent_id')->with(['user',"allReplies"]);
        }])->findOrFail($event_id);

        return response()->json([
            'msg' => 'Success',
            'data' => [
                'event' => [
                    'id' => $event->id,
                    'title' => $event->title,
                    'comments' => CommentRes::collection($event->comments),
                ],
            ],
        ], 200);
    });
});


